package com.taotao.enums.utils;

import com.taotao.enums.BaseEnum;
import com.taotao.enums.BaseEnumView;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BaseEnumUtils {

    public static String getCodes(Class<? extends BaseEnum> enumClass) {
        try {
            //反射调用枚举的values方法
            BaseEnum[] values = getValues(enumClass);
            if (null == values || 0 == values.length) {
                return null;
            }

            List<String> list = new ArrayList<>(values.length);


            for (BaseEnum e : values) {
                list.add(e.getCode().toString());
            }

            return StringUtil.join(",", list);
        } catch (Exception e) {
            log.error("", e);
        }

        return null;

    }

    public static <T extends BaseEnum> T getByCodeStr(Class<T> enumClass, String code) {
        try {
            //反射调用枚举的values方法
            T[] values = getValues(enumClass);
            if (null == values || 0 == values.length) {
                return null;
            }

            for (T e : values) {
                if (Objects.equals(e.getCode().toString(), code)) {
                    return e;
                }
            }

        } catch (Exception e) {
            log.error("", e);
        }

        return null;

    }


    public static <T extends BaseEnum, K> T getByCode(Class<T> enumClass, K code) {
        try {
            //反射调用枚举的values方法
            T[] values = getValues(enumClass);
            if (null == values || 0 == values.length) {
                return null;
            }

            for (T e : values) {
                if (Objects.equals(e.getCode(), code)) {
                    return e;
                }
            }

        } catch (Exception e) {
            log.error("", e);
        }

        return null;

    }

    public static String getDscr(Class<? extends BaseEnum> enumClass) {
        try {
            //反射调用枚举的values方法
            BaseEnum[] values = getValues(enumClass);
            if (null == values || 0 == values.length) {
                return null;
            }


            StringBuilder s = new StringBuilder();

            for (BaseEnum e : values) {
                s.append(",").append(e.getCode()).append("-").append(e.getText());
            }
            return s.toString().substring(1);

        } catch (Exception e) {
            log.error("", e);
        }

        return null;
    }


    public static <T extends BaseEnum, K> String getDisplayName(Class<T> enumClass, K code) {
        T e = getByCode(enumClass, code);
        if (null != e) {
            return e.getText();
        }

        return null;
    }


    public static String getDisplayNames(Class<? extends BaseEnum> enumClass, Object code, String separator) {

        BaseEnum[] values = getValues(enumClass);
        StringBuilder sb = new StringBuilder();
        for (BaseEnum t : values) {
            if (Objects.equals(t.getCode(), code)) {
                sb.append(t.getText()).append(separator);
            }
        }

        return sb.substring(0, sb.length() - 1);
    }


    public static <T extends BaseEnum> T[] getValues(Class<T> enumClass) {
        try {
            return (T[]) enumClass.getMethod("values").invoke(new Object(), new Object[]{});
        } catch (Exception e) {
            log.error("", e);
        }

        return null;
    }


    public static List<BaseEnumView> getCodeTextEnumViewList(Class<? extends BaseEnum> enumClass) {
        try {
            //反射调用枚举的values方法
            BaseEnum[] values = getValues(enumClass);
            if (null == values || 0 == values.length) {
                return null;
            }

            List<BaseEnumView> list = new ArrayList<>(values.length);


            for (BaseEnum e : values) {
                list.add(new BaseEnumView(e.getText(), e.getCode().toString()));
            }

            return list;
        } catch (Exception e) {
            log.error("", e);
        }

        return null;
    }


    /**
     * 设置枚举类型字段
     *
     * @param setter setter方法
     * @param <T>
     */
    public static <T> void setEnumField(Function<T, Void> setter, T o) {
        setter.apply(o);
    }


    /**
     * 执行方法
     *
     * @param methodName 方法名
     * @param arg        参数
     * @Param target 执行对象
     */
    private static Object inmokeSetMedthod(final String methodName, Object arg, Object target)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = target.getClass().getDeclaredMethod(methodName, arg.getClass());
        return method.invoke(target, arg);
    }


}
